<?php
require_once('model/Models.php');
require_once('exceptions/UserDataException.php');
require_once('exceptions/AuthenticationException.php');

class UserManager {

	public function __construct() {}

	/**
	 *
	 * @param unknown_type $name
	 * @param unknown_type $password
	 */
	public function authenticateUser($sUsername, $sPassword) {
		$oQuery = new Morph_Query();
		$oQuery->property('username')
				->equals($sUsername)
				->property('password')
				->equals($sPassword);

		try {
			$oUser = $this->getUserFromDB($oQuery);
			if($oUser) {
				return $oUser;
			} else {
				throw new AuthenticationException("Username oder Passwort falsch");
			}
		} catch(Exception $e) {
			if( $e instanceof Morph_Exception_ObjectNotFound) {
				throw new AuthenticationException("Username oder Passwort falsch");
			} else if($e instanceof AuthenticationException) {
				throw $e;
			} else {
				throw new AuthenticationException("Datenbankfehler");
			}
		}

	}

	/**
	 *
	 */
	public function getUser($sUserID, $sHash) {
		$oQuery = new Morph_Query();
		$oQuery->property('userID')
				->equals($sUserID)
				->property('hash')
				->equals($sHash);

		try {
			$oUser = $this->getUserFromDB($oQuery);
			if($oUser)
				return $oUser;
			else
				throw new Exception();
		} catch(Exception $e) {
			throw new Exception("User konnte nicht gefunden werden");
		}
	}

	/**
	 *
	 */
	public function getUserAsArray($sUserID, $sHash) {
		try {
			return $this->getUser($sUserID, $sHash)->__toArray();
		} catch(Exception $e) {
			throw $e;
		}
	}

	/**
	 *
	 */
	public function saveUser($sUserID, $sHash, $asUserData) {
		$mongo = new Mongo();
		Morph_Storage::init($mongo->selectDB('befragungssystem'));
		
		try {
			$oUser = $this->getUser($sUserID, $sHash);
			
			// assign user data
			$oUser->firstName = $asUserData['firstName'];
			$oUser->lastName = $asUserData['lastName'];
			$oUser->street = $asUserData['street'];
			$oUser->number = $asUserData['number'];
			$oUser->zip = $asUserData['zip'];
			$oUser->city = $asUserData['city'];
			$oUser->email = $asUserData['email'];
			
			// assign new username
			if($asUserData['username'] != "") {
				if($this->isUsernameAvailable($oUser->id(), $asUserData['username'])) {
					$oUser->username = $asUserData['username'];
				} else {
					throw new UserDataException("Dieser Accountname ist bereits vergeben");
				}
			} else {
				throw new UserDataException("Geben Sie einen Accountnamen an");
			}
							
			// assign new password
			if($asUserData['password'] != "") {
				if($oUser->password == $asUserData['password']) {
					if($asUserData['newPassword1'] != "" && $asUserData['newPassword2'] != "") {
					    if($asUserData['newPassword1'] == $asUserData['newPassword2']) {
							$oUser->password = $asUserData['newPassword1'];
					    } else {
					    	throw new UserDataException("Das neue Passwort wurde nicht korrekt wiederholt");
					    }
					} else {
						throw new UserDataException("Geben Sie das neue Passwort und seine Wiederholung an");
					}
				} else {
					throw new UserDataException("Das aktuelle Passwort ist nicht korrekt");
				}
			} else {
				throw new UserDataException("Geben Sie das aktuelle Passwort an");
			}
			
			$oUser->save();
		} catch(Exception $e) {
			throw $e;
		}
	}

	/**
	 *
	 * Enter description here ...
	 * @param unknown_type $oQuery
	 */
	private function getUserFromDB($oQuery) {
		$mongo = new Mongo();
		Morph_Storage::init($mongo->selectDB('befragungssystem'));

		try {
			$oUser = new User();
			$oUser = $oUser->findOneByQuery($oQuery);

			return $oUser;
		} catch(Exception $e) {
			throw $e;
		}
	}
	
	/**
	 * Check if the username is taken by a user with an ID different from
	 * $sID.
	 * 
	 * @param unknown_type $sID
	 * @param unknown_type $sUsername
	 * 
	 * @return true username is not taken by another User
	 *         false username is taken by another User
	 */
	private function isUsernameAvailable($sID, $sUsername) {
		$oQuery = new Morph_Query();
		$oQuery->property('username')->equals($sUsername)
			   ->property('_id')->notEqualTo($sID);
		
		try {
			$this->getUserFromDB($oQuery);
			return false;
		} catch(Morph_Exception_ObjectNotFound $e) {
			return true;
		}
	}
}
?>
